package com.yum.Iterator.List.YArrayList;

import com.yum.Iterator.Collection.YCollection;
import com.yum.Iterator.Arrays.YArrays;
import com.yum.Iterator.List.YList;
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;

import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.function.Consumer;

/**
 *
 * @param <E>
 */
public class YArrayList<E> implements YList<E>,Iterable<E> {

    private static final int INIT_SIZE = 10;

    //YArrayList被修改的次数 包括增加，移除...
    protected transient int modCount = 0;

    //空数组
    private static final Object[] INIT_ARRAY = {};

    //帮助原YArrayList扩容
    private Object[] oldArray;

    //存储数据的数组
    transient Object[] eleData;

    //记录老的容量 帮助YArrayList扩容
    private int oldSize;

    //大小
    private int size;

    /**
     * 默认无参构造器 当用户调用时 初始化一个空的数组
     */
    public YArrayList(){
        this.eleData = INIT_ARRAY;
    }

    /**
     * 当用户调用此构造器时 用户传入指定大小 对指定大小做出判断
     * @param size
     */
    public YArrayList(int size) {
        //判断size
        if(size > 0){ //size大于零时 创建一个size长的数组
            this.eleData = new Object[size];
        }
        else if(size == 0){ //size等于0时 默认为INIT_ARRAY空数组
            this.eleData = INIT_ARRAY;
        }
        else{ //如果size小于0 则报错
            throw new IllegalArgumentException("长度错误:" + size);
        }
    }

    public YArrayList(YCollection<? extends E> collection){


    }

    /**
     * YArrayList大小
     * @return size
     */
    @Override
    public int size() {
        return size;
    }

    @Override
    public E[] toArray(E[] a) {
        return null;
    }


    /**
     * 判断YArrayList是否为空
     * @return true:为空 false:不为空
     */
    @Override
    public boolean isEmpty() {
        if(eleData.length <= 0){
            return true;
        }
        return false;
    }

    /**
     * YArrayList添加功能
     * @param value 用户存入的值
     */
    @Override
    public boolean add(E value) {
        //检查数组是否为初始数组
        checkArray(size);
        if(size+1>eleData.length){ //先判断当前数组大小是否够用户存入值,若不够则扩容
            //扩容方法
            Expansion();
            //内存释放
            Inclear();
        }
        //把值存入数组中
        eleData[size] = value;
        //大小自增
        size++;
        //修改数自增
        modCount++;
        return true;
    }

    @Override
    public boolean addAll(YCollection<? extends E> Yc) {
        return false;
    }

    @Override
    public void clear() {

    }

    @Override
    public boolean contains(Object o) {
        if(o == null){
            for (int i=0;i<size;i++){
                return eleData[i] == null;
            }
        }
        if (eleData.length > 0){
            for (int i=0;i<size;i++){
                return eleData.equals(o);
            }
        }
        return false;
    }

    @Override
    public boolean contatinsAll(YCollection<?> Yc) {
        return false;
    }



    /**
     * 获取对应索引的对应值
     * @param index 索引值
     * @return 值
     */
    @Override
    public E getValue(int index) {
        //判断index是否大于数组长度 如果大于则报错
        if(index > eleData.length){
            throw new IllegalArgumentException("长度错误:"+index);
        }
        if(index >= 0){
            return (E) eleData[index];
        }
        return null;
    }

    /**
     * 更改对应索引里面的对应值
     * @param index 索引
     * @param value 要修改成的值
     * @return false:修改失败 true:修改成功
     */
    @Override
    public boolean setValue(int index,E value) {
        //判断index是否大于数组的长度
        if(index > eleData.length){
            return false;
        }
        eleData[index] = value;
        return true;

    }


    /**
     * 拷贝一份动态数组属于浅拷贝 浅拷贝:只复制某个对象的指针
     * @return 动态数组
     */
    @Override
    public Object clone() {
        try{
            //Object clone()用于创建并返回一个对象的拷贝
            YArrayList<?> v = (YArrayList<?>) super.clone();
            //将数组浅拷贝一份
            v.eleData = YArrays.copyOf(eleData,size);
            //modCount归零 新的YArrayList中默认为0
            v.modCount = 0;
            return v;
        }
        catch (CloneNotSupportedException e){
            throw new InternalException(e.getMessage());
        }

    }

    /**
     * 移除对应索引的对应值
     * @param index 索引
     * @return false:未找到,true:成功移除
     */
    public boolean remove(int index) {

        if(index >= size){
            throw new IllegalArgumentException("错误:索引大过YArrayList的长度:" + index);
        }
        modCount++;
        fastRemove(index);

        return true;
    }

    /**
     * 将对应相移除
     * @param value 对应值
     * @return false:失败(YArrayList为空) true:成功
     */
    public boolean remove(Object value){
        if(value == null){
            for(int i=0;i<size;i++){
                if(eleData[i] == null){
                    fastRemove(i);
                    return true;
                }
            }
        }
        else{
            for (int i=0;i<size;i++){
                if(eleData[i].equals(value)){
                    fastRemove(i);
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean removeAll(YCollection<?> Yc) {
        return false;
    }

    /**
     * 移除YArrayList中的所有项
     * @return false:失败(YArrayList为空),true:成功
     */
    public boolean removeAll() {
        if(eleData.length > 0){
            for(int i=0;i<eleData.length;i++){
                eleData[0] = null;
            }
            modCount++;
            size = 0;
            return true;
        }
        else {
            return false;
        }

    }

    /**
     * 查找对应值的对应索引
     * @param value 查找值
     * @return 索引 -1:未找到
     */
    @Override
    public int indexOf(Object value) {
        if(value == null){
            for (int i=0;i<size;i++){
                if(eleData[i]==null){
                    return i;
                }
            }
        }
        if (eleData.length > 0){
            for (int i=0;i<size;i++){
                if(eleData[i].equals(value)){
                    return i;
                }
            }
        }
        return -1;
    }


    /**
     * 将旧的数组里面的值拷贝到新数组里面 YArrayList自动扩容时会使用此方法
     * @param newArray 新数组
     * @param oldArray 旧数组
     */
    public void clone(Object[] newArray,Object[] oldArray){
        //遍历
        for(int i=0;i<oldArray.length;i++){
            newArray[i] = oldArray[i];
        }

    }

    /**
     * 将YArrayList转成数组返回
     * @return Obj数组
     */
    @Override
    public E[] toArray(){
        return (E[]) YArrays.copyOf(eleData,size);
    }

    /**
     * 从后往前查找值
     * @param value 值
     * @return 倒索引
     */
    @Override
    public int lastIndexOf(Object value){
        if(value == null){
            for(int i=size-1;i>=0;i--){
                if(eleData[i] == null){
                    return i;
                }
            }
        }
        else {
            for (int i=size-1;i>=0;i--){
                if(eleData[i].equals(value)){
                    return i;
                }
            }
        }
        return -1;
    }


    /**
     * 查看YArrayList里面是否有此值
     * @param o 值
     * @return false:未找到 true:找到
     */
    public boolean contanins(Object o){
        return indexOf(o) >= 0;
    }


    @Override
    public void forEach(Consumer<? super E> action) {
        if(action == null){
            throw new NullPointerException();
        }
        final int expectedModCount = modCount;
        final E[] eleData = (E[]) this.eleData;
        final int size = this.size;
        for(int i=0;i<size;i++){
            action.accept(eleData[i]);
        }
        if(expectedModCount != modCount){
            throw new ConcurrentModificationException();
        }
    }



    /**
     * 返回迭代器
     * @return 迭代器
     */
    @Override
    public Iterator<E> iterator(){
        return new Yiteroo();
    }


    /**
     * 匿名内部类实现迭代器
     */
    private class Yiteroo implements Iterator<E>{

        //游标
        private int cuvion;

        /**
         * 查看是否存在下个元素
         * @return true:存在 false:不存在
         */
        @Override
        public boolean hasNext() {
            return size > cuvion;
        }

        /**
         * 返回当前值 游标向前移
         * @return 游标对应值
         */
        @Override
        public E next() {

            E reuslt = getValue(cuvion);
            cuvion++;
            return reuslt;

        }



    }


    /**
     * 把数组中后面的数覆盖前面的 然后size-1
     * @param index 索引
     */
    private void fastRemove(int index){
        modCount++;
        int numMove = size - index - 1;
        if(numMove > 0){
            System.arraycopy(eleData,index+1,eleData,index,numMove);
        }
        eleData[--size] = null;
    }


    /**
     * 自动扩容
     */
    private void Expansion(){
        //将原有的长度赋值给oldSize
        oldSize = eleData.length;
        //初始化oldArray
        oldArray = new Object[oldSize];
        //将eleData里面的值赋值给oldArray
        clone(oldArray,eleData);
        //将eleData扩容 扩容长度为原数组的1.5倍
        eleData = new Object[oldSize + (oldSize>>1)];
        //将已经扩容好的eleData再赋回原有值
        clone(eleData,oldArray);
    }

    private void checkArray(int size){
        if(eleData == INIT_ARRAY){
            eleData = new Object[INIT_SIZE];
        }
    }

    /**
     * 清理内存
     */
    private void Inclear(){
        oldArray = null;
    }


}
